/**********************************************************************
*  Copyright (c) 2007 - Victor Jacobs - victor.jacobs@gmail.com
*
*  Permission is hereby granted, free of charge, to any person
*  obtaining a copy of this software and associated documentation
*  files (the "Software"), to deal in the Software without
*  restriction, including without limitation the rights to use,
*  copy, modify, merge, publish, distribute, sublicense, and/or sell
*  copies of the Software, and to permit persons to whom the
*  Software is furnished to do so, subject to the following
*  conditions:
*
*  The above copyright notice and this permission notice shall be
*  included in all copies or substantial portions of the Software.
*
*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
*  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
*  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
*  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
*  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
*  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
*  OTHER DEALINGS IN THE SOFTWARE.
**********************************************************************/

using System;
using System.Collections.Generic;
using System.Text;

namespace Vj.MathLibrary.Matrix
{
    /// <summary>
    /// Used for 4x4 Transformation Matrix operations
    /// </summary>
    public class TransformationHelper
    {
        public static MatrixDouble GetXRotMatrix(double angle)
        {
            MatrixDouble xRotM = new MatrixDouble(4, 4);
            double angleRad = angle * (Math.PI / 180.0);

            xRotM[0, 0] = 1;
            xRotM[1, 1] = Math.Cos(angleRad);
            xRotM[1, 2] = -Math.Sin(angleRad);
            xRotM[2, 1] = Math.Sin(angleRad);
            xRotM[2, 2] = Math.Cos(angleRad);
            xRotM[3, 3] = 1;

            return xRotM;
        }

        public static MatrixDouble GetYRotMatrix(double angle)
        {
            MatrixDouble yRotM = new MatrixDouble(4, 4);
            double angleRad = angle * (Math.PI / 180.0);

            yRotM[0, 0] = Math.Cos(angleRad);
            yRotM[0, 2] = Math.Sin(angleRad);
            yRotM[1, 1] = 1;
            yRotM[2, 0] = -Math.Sin(angleRad);
            yRotM[2, 2] = Math.Cos(angleRad);
            yRotM[3, 3] = 1;

            return yRotM;
        }

        public static MatrixDouble GetZRotMatrix(double angle)
        {
            MatrixDouble zRotM = new MatrixDouble(4, 4);
            double angleRad = angle * (Math.PI / 180.0);

            zRotM[0, 0] = Math.Cos(angleRad);
            zRotM[0, 1] = -Math.Sin(angleRad);
            zRotM[1, 0] = Math.Sin(angleRad);
            zRotM[1, 1] = Math.Cos(angleRad);
            zRotM[2, 2] = 1;
            zRotM[3, 3] = 1;

            return zRotM;
        }

        public static MatrixDouble GetRotMatrix(double x, double y, double z, double angle)
        {
            // normalize x,y,z

            MatrixDouble rotM = new MatrixDouble(4, 4);
            double angleRad = angle * (Math.PI / 180.0);

            double t = 1 - Math.Cos(angleRad);
            double c = Math.Cos(angleRad);
            double s = Math.Sin(angleRad);

            rotM[0, 0] = t * x * x + c;
            rotM[1, 0] = t * x * y - s * z;
            rotM[2, 0] = t * x * y + s * y;
            rotM[0, 1] = t * x * y + s * z;
            rotM[1, 1] = t * y * y + c;
            rotM[2, 1] = t * y * z - s * x;
            rotM[0, 2] = t * x * z - s * y;
            rotM[1, 2] = t * y * z + s * x;
            rotM[2, 2] = t * z * z + c;
            rotM[3, 3] = 1;


            return rotM;
        }

        public static MatrixDouble GetScaleMatrix(double scaleFactor)
        {
            MatrixDouble scaleM = new MatrixDouble(4, 4);

            scaleM[0, 0] = scaleFactor;
            scaleM[1, 1] = scaleFactor;
            scaleM[2, 2] = scaleFactor;
            scaleM[3, 3] = 1;

            return scaleM;
        }

        public static MatrixDouble GetScaleMatrix(double xFactor, double yFactor, double zFactor)
        {
            MatrixDouble scaleM = new MatrixDouble(4, 4);

            scaleM[0, 0] = xFactor;
            scaleM[1, 1] = yFactor;
            scaleM[2, 2] = zFactor;
            scaleM[3, 3] = 1;

            return scaleM;
        }

        
        public static MatrixDouble GetTranslationMatrix(double x, double y, double z)
        {
            MatrixDouble transM = new MatrixDouble(4, 4);

            transM[0, 3] = x;
            transM[1, 3] = y;
            transM[2, 3] = z;
            transM[0, 0] = 1;
            transM[1, 1] = 1;
            transM[2, 2] = 1;
            transM[3, 3] = 1;

            return transM;
        }

        public static MatrixDouble GetIdentityMatrix()
        {
            MatrixDouble identityM = new MatrixDouble(4, 4);
            identityM[0, 0] = 1;
            identityM[1, 1] = 1;
            identityM[2, 2] = 1;
            identityM[3, 3] = 1;

            return identityM;
        }




    }
}
